home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / varray.c < prev    next >
C/C++ Source or Header  |  1999-02-04  |  46KB  |  1,434 lines

  1. /* $Id: varray.c,v 3.6 1998/08/21 01:50:53 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: varray.c,v $
  26.  * Revision 3.6  1998/08/21 01:50:53  brianp
  27.  * added support for texture coordinate set interleave factor
  28.  *
  29.  * Revision 3.5  1998/06/07 22:18:52  brianp
  30.  * implemented GL_EXT_multitexture extension
  31.  *
  32.  * Revision 3.4  1998/03/27 04:26:44  brianp
  33.  * fixed G++ warnings
  34.  *
  35.  * Revision 3.3  1998/02/20 04:53:07  brianp
  36.  * implemented GL_SGIS_multitexture
  37.  *
  38.  * Revision 3.2  1998/02/01 20:05:10  brianp
  39.  * added glDrawRangeElements()
  40.  *
  41.  * Revision 3.1  1998/02/01 16:37:19  brianp
  42.  * added GL_EXT_rescale_normal extension
  43.  *
  44.  * Revision 3.0  1998/01/31 21:06:45  brianp
  45.  * initial rev
  46.  *
  47.  */
  48.  
  49.  
  50.  
  51. /*
  52.  * NOTE:  At this time, only three vertex array configurations are optimized:
  53.  *  1.  glVertex3fv(), zero stride
  54.  *  2.  glNormal3fv() with glVertex3fv(), zero stride
  55.  *  3.  glNormal3fv() with glVertex4fv(), zero stride
  56.  *
  57.  * More optimized array configurations can be added.
  58.  */
  59.  
  60.  
  61. #ifdef PC_HEADER
  62. #include "all.h"
  63. #else
  64. #include <stdlib.h>
  65. #include <string.h>
  66. #include "context.h"
  67. #include "enable.h"
  68. #include "dlist.h"
  69. #include "light.h"
  70. #include "macros.h"
  71. #include "texstate.h"
  72. #include "types.h"
  73. #include "varray.h"
  74. #include "vb.h"
  75. #include "vbfill.h"
  76. #include "vbrender.h"
  77. #include "vbxform.h"
  78. #include "xform.h"
  79. #endif
  80.  
  81.  
  82. void gl_VertexPointer( GLcontext *ctx,
  83.                        GLint size, GLenum type, GLsizei stride,
  84.                        const GLvoid *ptr )
  85. {
  86.    if (size<2 || size>4) {
  87.       gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
  88.       return;
  89.    }
  90.    if (stride<0) {
  91.       gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
  92.       return;
  93.    }
  94.    switch (type) {
  95.       case GL_SHORT:
  96.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLshort);
  97.          break;
  98.       case GL_INT:
  99.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLint);
  100.          break;
  101.       case GL_FLOAT:
  102.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLfloat);
  103.          break;
  104.       case GL_DOUBLE:
  105.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLdouble);
  106.          break;
  107.       default:
  108.          gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
  109.          return;
  110.    }
  111.    ctx->Array.VertexSize = size;
  112.    ctx->Array.VertexType = type;
  113.    ctx->Array.VertexStride = stride;
  114.    ctx->Array.VertexPtr = (void *) ptr;
  115. }
  116.  
  117.  
  118.  
  119.  
  120. void gl_NormalPointer( GLcontext *ctx,
  121.                        GLenum type, GLsizei stride, const GLvoid *ptr )
  122. {
  123.    if (stride<0) {
  124.       gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
  125.       return;
  126.    }
  127.    switch (type) {
  128.       case GL_BYTE:
  129.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLbyte);
  130.          break;
  131.       case GL_SHORT:
  132.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLshort);
  133.          break;
  134.       case GL_INT:
  135.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLint);
  136.          break;
  137.       case GL_FLOAT:
  138.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLfloat);
  139.          break;
  140.       case GL_DOUBLE:
  141.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLdouble);
  142.          break;
  143.       default:
  144.          gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
  145.          return;
  146.    }
  147.    ctx->Array.NormalType = type;
  148.    ctx->Array.NormalStride = stride;
  149.    ctx->Array.NormalPtr = (void *) ptr;
  150. }
  151.  
  152.  
  153.  
  154. void gl_ColorPointer( GLcontext *ctx,
  155.                       GLint size, GLenum type, GLsizei stride,
  156.                       const GLvoid *ptr )
  157. {
  158.    if (size<3 || size>4) {
  159.       gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
  160.       return;
  161.    }
  162.    if (stride<0) {
  163.       gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
  164.       return;
  165.    }
  166.    switch (type) {
  167.       case GL_BYTE:
  168.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLbyte);
  169.          break;
  170.       case GL_UNSIGNED_BYTE:
  171.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLubyte);
  172.          break;
  173.       case GL_SHORT:
  174.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLshort);
  175.          break;
  176.       case GL_UNSIGNED_SHORT:
  177.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLushort);
  178.          break;
  179.       case GL_INT:
  180.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLint);
  181.          break;
  182.       case GL_UNSIGNED_INT:
  183.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLuint);
  184.          break;
  185.       case GL_FLOAT:
  186.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLfloat);
  187.          break;
  188.       case GL_DOUBLE:
  189.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLdouble);
  190.          break;
  191.       default:
  192.          gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
  193.          return;
  194.    }
  195.    ctx->Array.ColorSize = size;
  196.    ctx->Array.ColorType = type;
  197.    ctx->Array.ColorStride = stride;
  198.    ctx->Array.ColorPtr = (void *) ptr;
  199. }
  200.  
  201.  
  202.  
  203. void gl_IndexPointer( GLcontext *ctx,
  204.                       GLenum type, GLsizei stride, const GLvoid *ptr )
  205. {
  206.    if (stride<0) {
  207.       gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
  208.       return;
  209.    }
  210.    switch (type) {
  211.       case GL_SHORT:
  212.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLbyte);
  213.          break;
  214.       case GL_INT:
  215.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLint);
  216.          break;
  217.       case GL_FLOAT:
  218.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLfloat);
  219.          break;
  220.       case GL_DOUBLE:
  221.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLdouble);
  222.          break;
  223.       default:
  224.          gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
  225.          return;
  226.    }
  227.    ctx->Array.IndexType = type;
  228.    ctx->Array.IndexStride = stride;
  229.    ctx->Array.IndexPtr = (void *) ptr;
  230. }
  231.  
  232.  
  233.  
  234. void gl_TexCoordPointer( GLcontext *ctx,
  235.                          GLint size, GLenum type, GLsizei stride,
  236.                          const GLvoid *ptr )
  237. {
  238.    GLuint texSet = ctx->Texture.CurrentSet;
  239.    if (size<1 || size>4) {
  240.       gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
  241.       return;
  242.    }
  243.    if (stride<0) {
  244.       gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
  245.       return;
  246.    }
  247.    switch (type) {
  248.       case GL_SHORT:
  249.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLshort);
  250.          break;
  251.       case GL_INT:
  252.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLint);
  253.          break;
  254.       case GL_FLOAT:
  255.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLfloat);
  256.          break;
  257.       case GL_DOUBLE:
  258.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLdouble);
  259.          break;
  260.       default:
  261.          gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
  262.          return;
  263.    }
  264.    ctx->Array.TexCoordSize[texSet] = size;
  265.    ctx->Array.TexCoordType[texSet] = type;
  266.    ctx->Array.TexCoordStride[texSet] = stride;
  267.    ctx->Array.TexCoordPtr[texSet] = (void *) ptr;
  268. }
  269.  
  270.  
  271.  
  272. /* GL_SGIS_multitexture */
  273. void gl_MultiTexCoordPointer( GLcontext *ctx, GLenum target,
  274.                               GLint size, GLenum type, GLsizei stride,
  275.                               const GLvoid *ptr )
  276. {
  277.    GLuint texSet;
  278.    if (target < GL_TEXTURE0_SGIS || target > GL_TEXTURE1_SGIS) {
  279.       gl_error(ctx, GL_INVALID_ENUM, "glMultiTexCoord(target)");
  280.       return;
  281.    }
  282.    if (stride<0) {
  283.       gl_error( ctx, GL_INVALID_VALUE, "glMultiTexCoordPointer(stride)" );
  284.       return;
  285.    }
  286.    if (size<1 || size>4) {
  287.       gl_error( ctx, GL_INVALID_VALUE, "glMultiTexCoordPointer(size)" );
  288.       return;
  289.    }
  290.    texSet = target - GL_TEXTURE0_SGIS;
  291.    switch (type) {
  292.       case GL_SHORT:
  293.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLshort);
  294.          break;
  295.       case GL_INT:
  296.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLint);
  297.          break;
  298.       case GL_FLOAT:
  299.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLfloat);
  300.          break;
  301.       case GL_DOUBLE:
  302.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLdouble);
  303.          break;
  304.       default:
  305.          gl_error( ctx, GL_INVALID_ENUM, "glMultiTexCoordPointer(type)" );
  306.          return;
  307.    }
  308.    ctx->Array.TexCoordSize[texSet] = size;
  309.    ctx->Array.TexCoordType[texSet] = type;
  310.    ctx->Array.TexCoordStride[texSet] = stride;
  311.    ctx->Array.TexCoordPtr[texSet] = (void *) ptr;
  312. }
  313.  
  314.  
  315.  
  316. void gl_InterleavedTextureCoordSets( GLcontext *ctx, GLint factor )
  317. {
  318.    GLint maxSets = gl_max_texture_coord_sets(ctx);
  319.    if (factor < 1 || factor > maxSets) {
  320.       gl_error( ctx, GL_INVALID_VALUE, "glInterleavedTextureCoordSets" );
  321.       return;
  322.    }
  323.    ctx->Array.TexCoordInterleaveFactor = factor;
  324. }
  325.  
  326.  
  327.  
  328. void gl_EdgeFlagPointer( GLcontext *ctx,
  329.                          GLsizei stride, const GLboolean *ptr )
  330. {
  331.    if (stride<0) {
  332.       gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
  333.       return;
  334.    }
  335.    ctx->Array.EdgeFlagStride = stride;
  336.    ctx->Array.EdgeFlagStrideB = stride ? stride : sizeof(GLboolean);
  337.    ctx->Array.EdgeFlagPtr = (GLboolean *) ptr;
  338. }
  339.  
  340.  
  341.  
  342. /*
  343.  * Execute
  344.  */
  345. void gl_ArrayElement( GLcontext *ctx, GLint i )
  346. {
  347.    struct vertex_buffer *VB = ctx->VB;
  348.    GLint count = VB->Count;
  349.    GLuint texSet;
  350.  
  351.    /* copy vertex data into the Vertex Buffer */
  352.  
  353.    if (ctx->Array.NormalEnabled) {
  354.       GLbyte *p = (GLbyte*) ctx->Array.NormalPtr
  355.                   + i * ctx->Array.NormalStrideB;
  356.       switch (ctx->Array.NormalType) {
  357.          case GL_BYTE:
  358.             VB->Normal[count][0] = BYTE_TO_FLOAT( p[0] );
  359.             VB->Normal[count][1] = BYTE_TO_FLOAT( p[1] );
  360.             VB->Normal[count][2] = BYTE_TO_FLOAT( p[2] );
  361.             break;
  362.          case GL_SHORT:
  363.             VB->Normal[count][0] = SHORT_TO_FLOAT( ((GLshort*)p)[0] );
  364.             VB->Normal[count][1] = SHORT_TO_FLOAT( ((GLshort*)p)[1] );
  365.             VB->Normal[count][2] = SHORT_TO_FLOAT( ((GLshort*)p)[2] );
  366.             break;
  367.          case GL_INT:
  368.             VB->Normal[count][0] = INT_TO_FLOAT( ((GLint*)p)[0] );
  369.             VB->Normal[count][1] = INT_TO_FLOAT( ((GLint*)p)[1] );
  370.             VB->Normal[count][2] = INT_TO_FLOAT( ((GLint*)p)[2] );
  371.             break;
  372.          case GL_FLOAT:
  373.             VB->Normal[count][0] = ((GLfloat*)p)[0];
  374.             VB->Normal[count][1] = ((GLfloat*)p)[1];
  375.             VB->Normal[count][2] = ((GLfloat*)p)[2];
  376.             break;
  377.          case GL_DOUBLE:
  378.             VB->Normal[count][0] = ((GLdouble*)p)[0];
  379.             VB->Normal[count][1] = ((GLdouble*)p)[1];
  380.             VB->Normal[count][2] = ((GLdouble*)p)[2];
  381.             break;
  382.          default:
  383.             gl_problem(ctx, "Bad normal type in gl_ArrayElement");
  384.             return;
  385.       }
  386.       VB->MonoNormal = GL_FALSE;
  387.    }
  388.    else {
  389.       VB->Normal[count][0] = ctx->Current.Normal[0];
  390.       VB->Normal[count][1] = ctx->Current.Normal[1];
  391.       VB->Normal[count][2] = ctx->Current.Normal[2];
  392.    } 
  393.  
  394.    /* TODO: directly set VB->Fcolor instead of calling a glColor command */
  395.    if (ctx->Array.ColorEnabled) {
  396.       GLbyte *p = (GLbyte*) ctx->Array.ColorPtr + i * ctx->Array.ColorStrideB;
  397.       switch (ctx->Array.ColorType) {
  398.          case GL_BYTE:
  399.             switch (ctx->Array.ColorSize) {
  400.                case 4:   glColor4bv( (GLbyte*) p );   break;
  401.                case 3:   glColor3bv( (GLbyte*) p );   break;
  402.             }
  403.             break;
  404.          case GL_UNSIGNED_BYTE:
  405.             switch (ctx->Array.ColorSize) {
  406.                case 3:   glColor3ubv( (GLubyte*) p );   break;
  407.                case 4:   glColor4ubv( (GLubyte*) p );   break;
  408.             }
  409.             break;
  410.          case GL_SHORT:
  411.             switch (ctx->Array.ColorSize) {
  412.                case 3:   glColor3sv( (GLshort*) p );   break;
  413.                case 4:   glColor4sv( (GLshort*) p );   break;
  414.             }
  415.             break;
  416.          case GL_UNSIGNED_SHORT:
  417.             switch (ctx->Array.ColorSize) {
  418.                case 3:   glColor3usv( (GLushort*) p );   break;
  419.                case 4:   glColor4usv( (GLushort*) p );   break;
  420.             }
  421.             break;
  422.          case GL_INT:
  423.             switch (ctx->Array.ColorSize) {
  424.                case 3:   glColor3iv( (GLint*) p );   break;
  425.                case 4:   glColor4iv( (GLint*) p );   break;
  426.             }
  427.             break;
  428.          case GL_UNSIGNED_INT:
  429.             switch (ctx->Array.ColorSize) {
  430.                case 3:   glColor3uiv( (GLuint*) p );   break;
  431.                case 4:   glColor4uiv( (GLuint*) p );   break;
  432.             }
  433.             break;
  434.          case GL_FLOAT:
  435.             switch (ctx->Array.ColorSize) {
  436.                case 3:   glColor3fv( (GLfloat*) p );   break;
  437.                case 4:   glColor4fv( (GLfloat*) p );   break;
  438.             }
  439.             break;
  440.          case GL_DOUBLE:
  441.             switch (ctx->Array.ColorSize) {
  442.                case 3:   glColor3dv( (GLdouble*) p );   break;
  443.                case 4:   glColor4dv( (GLdouble*) p );   break;
  444.             }
  445.             break;
  446.          default:
  447.             gl_problem(ctx, "Bad color type in gl_ArrayElement");
  448.             return;
  449.       }
  450.       ctx->VB->MonoColor = GL_FALSE;
  451.    }
  452.  
  453.    /* current color has been updated. store in vertex buffer now */
  454.    {
  455.       COPY_4UBV( VB->Fcolor[count], ctx->Current.ByteColor );
  456.       if (ctx->Light.ColorMaterialEnabled) {
  457.          GLfloat color[4];
  458.          color[0] = ctx->Current.ByteColor[0] * (1.0F / 255.0F);
  459.          color[1] = ctx->Current.ByteColor[1] * (1.0F / 255.0F);
  460.          color[2] = ctx->Current.ByteColor[2] * (1.0F / 255.0F);
  461.          color[3] = ctx->Current.ByteColor[3] * (1.0F / 255.0F);
  462.          gl_set_material( ctx, ctx->Light.ColorMaterialBitmask, color );
  463.       }
  464.    }
  465.  
  466.    if (ctx->Array.IndexEnabled) {
  467.       GLbyte *p = (GLbyte*) ctx->Array.IndexPtr + i * ctx->Array.IndexStrideB;
  468.       switch (ctx->Array.IndexType) {
  469.          case GL_SHORT:
  470.             VB->Findex[count] = (GLuint) (*((GLshort*) p));
  471.             break;
  472.          case GL_INT:
  473.             VB->Findex[count] = (GLuint) (*((GLint*) p));
  474.             break;
  475.          case GL_FLOAT:
  476.             VB->Findex[count] = (GLuint) (*((GLfloat*) p));
  477.             break;
  478.          case GL_DOUBLE:
  479.             VB->Findex[count] = (GLuint) (*((GLdouble*) p));
  480.             break;
  481.          default:
  482.             gl_problem(ctx, "Bad index type in gl_ArrayElement");
  483.             return;
  484.       }
  485.       ctx->VB->MonoColor = GL_FALSE;
  486.    }
  487.    else {
  488.       VB->Findex[count] = ctx->Current.Index;
  489.    }
  490.  
  491.    for (texSet=0; texSet<MAX_TEX_SETS; texSet++) {
  492.        if (ctx->Array.TexCoordEnabled[texSet]) {
  493.           GLbyte *p = (GLbyte*) ctx->Array.TexCoordPtr[texSet]
  494.                       + i * ctx->Array.TexCoordStrideB[texSet];
  495.           VB->MultiTexCoord[texSet][count][1] = 0.0F;
  496.           VB->MultiTexCoord[texSet][count][2] = 0.0F;
  497.           VB->MultiTexCoord[texSet][count][3] = 1.0F;
  498.           switch (ctx->Array.TexCoordType[texSet]) {
  499.              case GL_SHORT:
  500.                 switch (ctx->Array.TexCoordSize[texSet]) {
  501.                    /* FALL THROUGH! */
  502.                    case 4:   VB->MultiTexCoord[texSet][count][3] = ((GLshort*) p)[3];
  503.                    case 3:   VB->MultiTexCoord[texSet][count][2] = ((GLshort*) p)[2];
  504.                    case 2:   VB->MultiTexCoord[texSet][count][1] = ((GLshort*) p)[1];
  505.                    case 1:   VB->MultiTexCoord[texSet][count][0] = ((GLshort*) p)[0];
  506.                 }
  507.                 break;
  508.              case GL_INT:
  509.                 switch (ctx->Array.TexCoordSize[texSet]) {
  510.                    /* FALL THROUGH! */
  511.                    case 4:   VB->MultiTexCoord[texSet][count][3] = ((GLint*) p)[3];
  512.                    case 3:   VB->MultiTexCoord[texSet][count][2] = ((GLint*) p)[2];
  513.                    case 2:   VB->MultiTexCoord[texSet][count][1] = ((GLint*) p)[1];
  514.                    case 1:   VB->MultiTexCoord[texSet][count][0] = ((GLint*) p)[0];
  515.                 }
  516.                 break;
  517.              case GL_FLOAT:
  518.                 switch (ctx->Array.TexCoordSize[texSet]) {
  519.                    /* FALL THROUGH! */
  520.                    case 4:   VB->MultiTexCoord[texSet][count][3] = ((GLfloat*) p)[3];
  521.                    case 3:   VB->MultiTexCoord[texSet][count][2] = ((GLfloat*) p)[2];
  522.                    case 2:   VB->MultiTexCoord[texSet][count][1] = ((GLfloat*) p)[1];
  523.                    case 1:   VB->MultiTexCoord[texSet][count][0] = ((GLfloat*) p)[0];
  524.                 }
  525.                 break;
  526.              case GL_DOUBLE:
  527.                 switch (ctx->Array.TexCoordSize[texSet]) {
  528.                    /* FALL THROUGH! */
  529.                    case 4:   VB->MultiTexCoord[texSet][count][3] = ((GLdouble*) p)[3];
  530.                    case 3:   VB->MultiTexCoord[texSet][count][2] = ((GLdouble*) p)[2];
  531.                    case 2:   VB->MultiTexCoord[texSet][count][1] = ((GLdouble*) p)[1];
  532.                    case 1:   VB->MultiTexCoord[texSet][count][0] = ((GLdouble*) p)[0];
  533.                 }
  534.                 break;
  535.              default:
  536.                 gl_problem(ctx, "Bad texcoord type in gl_ArrayElement");
  537.                 return;
  538.           }
  539.        }
  540.        else {
  541.           COPY_4V( VB->MultiTexCoord[texSet][count], ctx->Current.MultiTexCoord[texSet] );
  542.        }
  543.    }
  544.  
  545.    if (ctx->Array.EdgeFlagEnabled) {
  546.       GLbyte *b = (GLbyte*) ctx->Array.EdgeFlagPtr
  547.                   + i * ctx->Array.EdgeFlagStrideB;
  548.       VB->Edgeflag[count] = *((GLboolean*) b);
  549.    }
  550.    else {
  551.       VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  552.    }
  553.  
  554.    if (ctx->Array.VertexEnabled) {
  555.       GLbyte *b = (GLbyte*) ctx->Array.VertexPtr
  556.                   + i * ctx->Array.VertexStrideB;
  557.       VB->Obj[count][2] = 0.0F;
  558.       VB->Obj[count][3] = 1.0F;
  559.       switch (ctx->Array.VertexType) {
  560.          case GL_SHORT:
  561.             switch (ctx->Array.VertexSize) {
  562.                /* FALL THROUGH */
  563.                case 4:   VB->Obj[count][3] = ((GLshort*) b)[3];
  564.                case 3:   VB->Obj[count][2] = ((GLshort*) b)[2];
  565.                case 2:   VB->Obj[count][1] = ((GLshort*) b)[1];
  566.                          VB->Obj[count][0] = ((GLshort*) b)[0];
  567.             }
  568.             break;
  569.          case GL_INT:
  570.             switch (ctx->Array.VertexSize) {
  571.                /* FALL THROUGH */
  572.                case 4:   VB->Obj[count][3] = ((GLint*) b)[3];
  573.                case 3:   VB->Obj[count][2] = ((GLint*) b)[2];
  574.                case 2:   VB->Obj[count][1] = ((GLint*) b)[1];
  575.                          VB->Obj[count][0] = ((GLint*) b)[0];
  576.             }
  577.             break;
  578.          case GL_FLOAT:
  579.             switch (ctx->Array.VertexSize) {
  580.                /* FALL THROUGH */
  581.                case 4:   VB->Obj[count][3] = ((GLfloat*) b)[3];
  582.                case 3:   VB->Obj[count][2] = ((GLfloat*) b)[2];
  583.                case 2:   VB->Obj[count][1] = ((GLfloat*) b)[1];
  584.                          VB->Obj[count][0] = ((GLfloat*) b)[0];
  585.             }
  586.             break;
  587.          case GL_DOUBLE:
  588.             switch (ctx->Array.VertexSize) {
  589.                /* FALL THROUGH */
  590.                case 4:   VB->Obj[count][3] = ((GLdouble*) b)[3];
  591.                case 3:   VB->Obj[count][2] = ((GLdouble*) b)[2];
  592.                case 2:   VB->Obj[count][1] = ((GLdouble*) b)[1];
  593.                          VB->Obj[count][0] = ((GLdouble*) b)[0];
  594.             }
  595.             break;
  596.          default:
  597.             gl_problem(ctx, "Bad vertex type in gl_ArrayElement");
  598.             return;
  599.       }
  600.  
  601.       /* Only store vertex if Vertex array pointer is enabled */
  602.       count++;
  603.       VB->Count = count;
  604.       if (count==VB_MAX) {
  605.          gl_transform_vb_part1( ctx, GL_FALSE );
  606.       }
  607.  
  608.    }
  609.    else {
  610.       /* vertex array pointer not enabled: no vertex to process */
  611.    }
  612. }
  613.  
  614.  
  615.  
  616.  
  617. /*
  618.  * Save into display list
  619.  * Use external API entry points since speed isn't too important here
  620.  * and makes the code simpler.  Also, if GL_COMPILE_AND_EXECUTE then
  621.  * execute will happen too.
  622.  */
  623. void gl_save_ArrayElement( GLcontext *ctx, GLint i )
  624. {
  625.    GLuint texSet;
  626.    if (ctx->Array.NormalEnabled) {
  627.       GLbyte *p = (GLbyte*) ctx->Array.NormalPtr
  628.                   + i * ctx->Array.NormalStrideB;
  629.       switch (ctx->Array.NormalType) {
  630.          case GL_BYTE:
  631.             glNormal3bv( (GLbyte*) p );
  632.             break;
  633.          case GL_SHORT:
  634.             glNormal3sv( (GLshort*) p );
  635.             break;
  636.          case GL_INT:
  637.             glNormal3iv( (GLint*) p );
  638.             break;
  639.          case GL_FLOAT:
  640.             glNormal3fv( (GLfloat*) p );
  641.             break;
  642.          case GL_DOUBLE:
  643.             glNormal3dv( (GLdouble*) p );
  644.             break;
  645.          default:
  646.             gl_problem(ctx, "Bad normal type in gl_save_ArrayElement");
  647.             return;
  648.       }
  649.    }
  650.  
  651.    if (ctx->Array.ColorEnabled) {
  652.       GLbyte *p = (GLbyte*) ctx->Array.ColorPtr + i * ctx->Array.ColorStrideB;
  653.       switch (ctx->Array.ColorType) {
  654.          case GL_BYTE:
  655.             switch (ctx->Array.ColorSize) {
  656.                case 3:   glColor3bv( (GLbyte*) p );   break;
  657.                case 4:   glColor4bv( (GLbyte*) p );   break;
  658.             }
  659.             break;
  660.          case GL_UNSIGNED_BYTE:
  661.             switch (ctx->Array.ColorSize) {
  662.                case 3:   glColor3ubv( (GLubyte*) p );   break;
  663.                case 4:   glColor4ubv( (GLubyte*) p );   break;
  664.             }
  665.             break;
  666.          case GL_SHORT:
  667.             switch (ctx->Array.ColorSize) {
  668.                case 3:   glColor3sv( (GLshort*) p );   break;
  669.                case 4:   glColor4sv( (GLshort*) p );   break;
  670.             }
  671.             break;
  672.          case GL_UNSIGNED_SHORT:
  673.             switch (ctx->Array.ColorSize) {
  674.                case 3:   glColor3usv( (GLushort*) p );   break;
  675.                case 4:   glColor4usv( (GLushort*) p );   break;
  676.             }
  677.             break;
  678.          case GL_INT:
  679.             switch (ctx->Array.ColorSize) {
  680.                case 3:   glColor3iv( (GLint*) p );   break;
  681.                case 4:   glColor4iv( (GLint*) p );   break;
  682.             }
  683.             break;
  684.          case GL_UNSIGNED_INT:
  685.             switch (ctx->Array.ColorSize) {
  686.                case 3:   glColor3uiv( (GLuint*) p );   break;
  687.                case 4:   glColor4uiv( (GLuint*) p );   break;
  688.             }
  689.             break;
  690.          case GL_FLOAT:
  691.             switch (ctx->Array.ColorSize) {
  692.                case 3:   glColor3fv( (GLfloat*) p );   break;
  693.                case 4:   glColor4fv( (GLfloat*) p );   break;
  694.             }
  695.             break;
  696.          case GL_DOUBLE:
  697.             switch (ctx->Array.ColorSize) {
  698.                case 3:   glColor3dv( (GLdouble*) p );   break;
  699.                case 4:   glColor4dv( (GLdouble*) p );   break;
  700.             }
  701.             break;
  702.          default:
  703.             gl_problem(ctx, "Bad color type in gl_save_ArrayElement");
  704.             return;
  705.       }
  706.    }
  707.  
  708.    if (ctx->Array.IndexEnabled) {
  709.       GLbyte *p = (GLbyte*) ctx->Array.IndexPtr + i * ctx->Array.IndexStrideB;
  710.       switch (ctx->Array.IndexType) {
  711.          case GL_SHORT:
  712.             glIndexsv( (GLshort*) p );
  713.             break;
  714.          case GL_INT:
  715.             glIndexiv( (GLint*) p );
  716.             break;
  717.          case GL_FLOAT:
  718.             glIndexfv( (GLfloat*) p );
  719.             break;
  720.          case GL_DOUBLE:
  721.             glIndexdv( (GLdouble*) p );
  722.             break;
  723.          default:
  724.             gl_problem(ctx, "Bad index type in gl_save_ArrayElement");
  725.             return;
  726.       }
  727.    }
  728.  
  729.    for (texSet=0; texSet<MAX_TEX_SETS; texSet++) {
  730.       if (ctx->Array.TexCoordEnabled[texSet]) {
  731.          GLbyte *p = (GLbyte*) ctx->Array.TexCoordPtr[texSet]
  732.                      + i * ctx->Array.TexCoordStrideB[texSet];
  733.          GLenum target = (GLenum) (GL_TEXTURE0_SGIS + texSet);
  734.          switch (ctx->Array.TexCoordType[texSet]) {
  735.             case GL_SHORT:
  736.                switch (ctx->Array.TexCoordSize[texSet]) {
  737.                   case 1:   glMultiTexCoord1svSGIS( target, (GLshort*) p );   break;
  738.                   case 2:   glMultiTexCoord2svSGIS( target, (GLshort*) p );   break;
  739.                   case 3:   glMultiTexCoord3svSGIS( target, (GLshort*) p );   break;
  740.                   case 4:   glMultiTexCoord4svSGIS( target, (GLshort*) p );   break;
  741.                }
  742.                break;
  743.             case GL_INT:
  744.                switch (ctx->Array.TexCoordSize[texSet]) {
  745.                   case 1:   glMultiTexCoord1ivSGIS( target, (GLint*) p );   break;
  746.                   case 2:   glMultiTexCoord2ivSGIS( target, (GLint*) p );   break;
  747.                   case 3:   glMultiTexCoord3ivSGIS( target, (GLint*) p );   break;
  748.                   case 4:   glMultiTexCoord4ivSGIS( target, (GLint*) p );   break;
  749.                }
  750.                break;
  751.             case GL_FLOAT:
  752.                switch (ctx->Array.TexCoordSize[texSet]) {
  753.                   case 1:   glMultiTexCoord1fvSGIS( target, (GLfloat*) p );   break;
  754.                   case 2:   glMultiTexCoord2fvSGIS( target, (GLfloat*) p );   break;
  755.                   case 3:   glMultiTexCoord3fvSGIS( target, (GLfloat*) p );   break;
  756.                   case 4:   glMultiTexCoord4fvSGIS( target, (GLfloat*) p );   break;
  757.                }
  758.                break;
  759.             case GL_DOUBLE:
  760.                switch (ctx->Array.TexCoordSize[texSet]) {
  761.                   case 1:   glMultiTexCoord1dvSGIS( target, (GLdouble*) p );   break;
  762.                   case 2:   glMultiTexCoord2dvSGIS( target, (GLdouble*) p );   break;
  763.                   case 3:   glMultiTexCoord3dvSGIS( target, (GLdouble*) p );   break;
  764.                   case 4:   glMultiTexCoord4dvSGIS( target, (GLdouble*) p );   break;
  765.                }
  766.                break;
  767.             default:
  768.                gl_problem(ctx, "Bad texcoord type in gl_save_ArrayElement");
  769.                return;
  770.          }
  771.       }
  772.    }
  773.  
  774.    if (ctx->Array.EdgeFlagEnabled) {
  775.       GLbyte *b = (GLbyte*) ctx->Array.EdgeFlagPtr + i * ctx->Array.EdgeFlagStrideB;
  776.       glEdgeFlagv( (GLboolean*) b );
  777.    }
  778.  
  779.    if (ctx->Array.VertexEnabled) {
  780.       GLbyte *b = (GLbyte*) ctx->Array.VertexPtr
  781.                   + i * ctx->Array.VertexStrideB;
  782.       switch (ctx->Array.VertexType) {
  783.          case GL_SHORT:
  784.             switch (ctx->Array.VertexSize) {
  785.                case 2:   glVertex2sv( (GLshort*) b );   break;
  786.                case 3:   glVertex3sv( (GLshort*) b );   break;
  787.                case 4:   glVertex4sv( (GLshort*) b );   break;
  788.             }
  789.             break;
  790.          case GL_INT:
  791.             switch (ctx->Array.VertexSize) {
  792.                case 2:   glVertex2iv( (GLint*) b );   break;
  793.                case 3:   glVertex3iv( (GLint*) b );   break;
  794.                case 4:   glVertex4iv( (GLint*) b );   break;
  795.             }
  796.             break;
  797.          case GL_FLOAT:
  798.             switch (ctx->Array.VertexSize) {
  799.                case 2:   glVertex2fv( (GLfloat*) b );   break;
  800.                case 3:   glVertex3fv( (GLfloat*) b );   break;
  801.                case 4:   glVertex4fv( (GLfloat*) b );   break;
  802.             }
  803.             break;
  804.          case GL_DOUBLE:
  805.             switch (ctx->Array.VertexSize) {
  806.                case 2:   glVertex2dv( (GLdouble*) b );   break;
  807.                case 3:   glVertex3dv( (GLdouble*) b );   break;
  808.                case 4:   glVertex4dv( (GLdouble*) b );   break;
  809.             }
  810.             break;
  811.          default:
  812.             gl_problem(ctx, "Bad vertex type in gl_save_ArrayElement");
  813.             return;
  814.       }
  815.    }
  816. }
  817.  
  818.  
  819.  
  820. /*
  821.  * Execute
  822.  */
  823. void gl_DrawArrays( GLcontext *ctx,
  824.                     GLenum mode, GLint first, GLsizei count )
  825. {
  826.    struct vertex_buffer* VB = ctx->VB;
  827.    GLuint texSet = ctx->Texture.CurrentSet;
  828.    GLint i;
  829.    GLboolean need_edges;
  830.  
  831.    if (INSIDE_BEGIN_END(ctx)) {
  832.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
  833.       return;
  834.    }
  835.    if (count<0) {
  836.       gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
  837.       return;
  838.    }
  839.  
  840.    if (ctx->Primitive==GL_TRIANGLES || ctx->Primitive==GL_QUADS
  841.        || ctx->Primitive==GL_POLYGON) {
  842.       need_edges = GL_TRUE;
  843.    }
  844.    else {
  845.       need_edges = GL_FALSE;
  846.    }
  847.  
  848.    if (!ctx->Light.Enabled
  849.        && !ctx->Texture.Enabled
  850.        && ctx->Array.VertexEnabled && ctx->Array.VertexType==GL_FLOAT
  851.        && ctx->Array.VertexStride==0 && ctx->Array.VertexSize==3
  852.        && !ctx->Array.NormalEnabled
  853.        && !ctx->Array.ColorEnabled
  854.        && !ctx->Array.IndexEnabled
  855.        && !ctx->Array.TexCoordEnabled[texSet]
  856.        && !ctx->Array.EdgeFlagEnabled) {
  857.       /*
  858.        * SPECIAL CASE:  glVertex3fv() with no lighting
  859.        */
  860.       GLfloat (*vptr)[3];
  861.       GLint remaining;
  862.  
  863.       gl_Begin( ctx, mode );
  864.  
  865.       remaining = count;
  866. #ifndef __STORM__
  867.       vptr = (GLfloat (*)[3]) ctx->Array.VertexPtr + 3 * first;
  868. #else
  869.       vptr = (GLfloat (*)[3]) ctx->Array.VertexPtr;
  870.       vptr+= 3 * first;
  871. #endif
  872.       while (remaining>0) {
  873.          GLint vbspace, n;
  874.  
  875.          vbspace = VB_MAX - VB->Start;
  876.          n = MIN2( vbspace, remaining );
  877.  
  878.          gl_xform_points_3fv( n, VB->Eye+VB->Start, ctx->ModelViewMatrix, vptr );
  879.  
  880.          /* assign vertex colors */
  881.          {
  882.             GLint i, start = VB->Start;
  883.             for (i=0;i<n;i++) {
  884.                COPY_4UBV( VB->Fcolor[start+i], ctx->Current.ByteColor );
  885.             }
  886.          }
  887.  
  888.          /* assign polygon edgeflags */
  889.          if (need_edges) {
  890.             GLint i;
  891.             for (i=0;i<n;i++) {
  892.                VB->Edgeflag[VB->Start+i] = ctx->Current.EdgeFlag;
  893.             }
  894.          }
  895.  
  896.          remaining -= n;
  897.  
  898.          VB->MonoNormal = GL_FALSE;
  899.          VB->Count = VB->Start + n;
  900.          gl_transform_vb_part2( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  901.  
  902.          vptr += n;
  903.       }
  904.  
  905.       gl_End( ctx );
  906.    }
  907.    else if (!ctx->CompileFlag
  908.        && ctx->Light.Enabled
  909.        && !ctx->Texture.Enabled
  910.        && ctx->Array.VertexEnabled && ctx->Array.VertexType==GL_FLOAT
  911.        && ctx->Array.VertexStride==0 && ctx->Array.VertexSize==4
  912.        && ctx->Array.NormalEnabled && ctx->Array.NormalType==GL_FLOAT
  913.        && ctx->Array.NormalStride==0
  914.        && !ctx->Array.ColorEnabled
  915.        && !ctx->Array.IndexEnabled
  916.        && !ctx->Array.TexCoordEnabled[texSet]
  917.        && !ctx->Array.EdgeFlagEnabled) {
  918.       /*
  919.        * SPECIAL CASE:  glNormal3fv();  glVertex4fv();  with lighting
  920.        */
  921.       GLfloat (*vptr)[4], (*nptr)[3];
  922.       GLint remaining;
  923.  
  924.       gl_Begin( ctx, mode );
  925.  
  926.       remaining = count;
  927. #ifndef __STORM__
  928.       vptr = (GLfloat (*)[4]) ctx->Array.VertexPtr + 4 * first;
  929.       nptr = (GLfloat (*)[3]) ctx->Array.NormalPtr + 3 * first;
  930. #else
  931.       vptr = (GLfloat (*)[4]) ctx->Array.VertexPtr;
  932.       vptr += 4 * first;
  933.       nptr = (GLfloat (*)[3]) ctx->Array.NormalPtr;
  934.       nptr += 3 * first;
  935. #endif
  936.       while (remaining>0) {
  937.          GLint vbspace, n;
  938.  
  939.          vbspace = VB_MAX - VB->Start;
  940.          n = MIN2( vbspace, remaining );
  941.  
  942.          gl_xform_points_4fv( n, VB->Eye+VB->Start, ctx->ModelViewMatrix, vptr );
  943.          gl_xform_normals_3fv( n, VB->Normal+VB->Start, ctx->ModelViewInv, nptr,
  944.                                ctx->Transform.Normalize,
  945.                                ctx->Transform.RescaleNormals );
  946.  
  947.          /* assign polygon edgeflags */
  948.          if (need_edges) {
  949.             GLint i;
  950.             for (i=0;i<n;i++) {
  951.                VB->Edgeflag[VB->Start+i] = ctx->Current.EdgeFlag;
  952.             }
  953.          }
  954.  
  955.          remaining -= n;
  956.  
  957.          VB->MonoNormal = GL_FALSE;
  958.          VB->Count = VB->Start + n;
  959.          gl_transform_vb_part2( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  960.  
  961.          vptr += n;
  962.          nptr += n;
  963.       }
  964.  
  965.       gl_End( ctx );
  966.    }
  967.    else if (!ctx->CompileFlag
  968.        && ctx->Light.Enabled
  969.        && !ctx->Texture.Enabled
  970.        && ctx->Array.VertexEnabled && ctx->Array.VertexType==GL_FLOAT
  971.        && ctx->Array.VertexStride==0 && ctx->Array.VertexSize==3
  972.        && ctx->Array.NormalEnabled && ctx->Array.NormalType==GL_FLOAT
  973.        && ctx->Array.NormalStride==0
  974.        && !ctx->Array.ColorEnabled
  975.        && !ctx->Array.IndexEnabled
  976.        && !ctx->Array.TexCoordEnabled[texSet]
  977.        && !ctx->Array.EdgeFlagEnabled) {
  978.       /*
  979.        * SPECIAL CASE:  glNormal3fv();  glVertex3fv();  with lighting
  980.        */
  981.       GLfloat (*vptr)[3], (*nptr)[3];
  982.       GLint remaining;
  983.  
  984.       gl_Begin( ctx, mode );
  985.  
  986.       remaining = count;
  987. #ifndef __STORM__
  988.       vptr = (GLfloat (*)[3]) ctx->Array.VertexPtr + 3 * first;
  989.       nptr = (GLfloat (*)[3]) ctx->Array.NormalPtr + 3 * first;
  990. #else
  991.       vptr = (GLfloat (*)[3]) ctx->Array.VertexPtr;
  992.       vptr += 3 * first;
  993.       nptr = (GLfloat (*)[3]) ctx->Array.NormalPtr;
  994.       nptr += 3 * first;
  995. #endif
  996.       while (remaining>0) {
  997.          GLint vbspace, n;
  998.  
  999.          vbspace = VB_MAX - VB->Start;
  1000.          n = MIN2( vbspace, remaining );
  1001.  
  1002.          gl_xform_points_3fv( n, VB->Eye+VB->Start, ctx->ModelViewMatrix, vptr );
  1003.          gl_xform_normals_3fv( n, VB->Normal+VB->Start, ctx->ModelViewInv, nptr,
  1004.                                ctx->Transform.Normalize,
  1005.                                ctx->Transform.RescaleNormals );
  1006.  
  1007.          /* assign polygon edgeflags */
  1008.          if (need_edges) {
  1009.             GLint i;
  1010.             for (i=0;i<n;i++) {
  1011.                VB->Edgeflag[VB->Start+i] = ctx->Current.EdgeFlag;
  1012.             }
  1013.          }
  1014.  
  1015.          remaining -= n;
  1016.  
  1017.          VB->MonoNormal = GL_FALSE;
  1018.          VB->Count = VB->Start + n;
  1019.          gl_transform_vb_part2( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  1020.  
  1021.          vptr += n;
  1022.          nptr += n;
  1023.       }
  1024.  
  1025.       gl_End( ctx );
  1026.    }
  1027.    else {
  1028.       /*
  1029.        * GENERAL CASE:
  1030.        */
  1031.       gl_Begin( ctx, mode );
  1032.       for (i=0;i<count;i++) {
  1033.          gl_ArrayElement( ctx, first+i );
  1034.       }
  1035.       gl_End( ctx );
  1036.    }
  1037. }
  1038.  
  1039.  
  1040.  
  1041. /*
  1042.  * Save into a display list
  1043.  */
  1044. void gl_save_DrawArrays( GLcontext *ctx,
  1045.                          GLenum mode, GLint first, GLsizei count )
  1046. {
  1047.    GLint i;
  1048.  
  1049.    if (INSIDE_BEGIN_END(ctx)) {
  1050.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
  1051.       return;
  1052.    }
  1053.    if (count<0) {
  1054.       gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
  1055.       return;
  1056.    }
  1057.    switch (mode) {
  1058.       case GL_POINTS:
  1059.       case GL_LINES:
  1060.       case GL_LINE_STRIP:
  1061.       case GL_LINE_LOOP:
  1062.       case GL_TRIANGLES:
  1063.       case GL_TRIANGLE_STRIP:
  1064.       case GL_TRIANGLE_FAN:
  1065.       case GL_QUADS:
  1066.       case GL_QUAD_STRIP:
  1067.       case GL_POLYGON:
  1068.          /* OK */
  1069.          break;
  1070.       default:
  1071.          gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
  1072.          return;
  1073.    }
  1074.  
  1075.    /* Note: this will do compile AND execute if needed */
  1076.    gl_save_Begin( ctx, mode );
  1077.    for (i=0;i<count;i++) {
  1078.       gl_save_ArrayElement( ctx, first+i );
  1079.    }
  1080.    gl_save_End( ctx );
  1081. }
  1082.  
  1083.  
  1084.  
  1085.  
  1086. /*
  1087.  * Execute only
  1088.  */
  1089. void gl_DrawElements( GLcontext *ctx,
  1090.                       GLenum mode, GLsizei count,
  1091.                       GLenum type, const GLvoid *indices )
  1092. {
  1093.    
  1094.    if (INSIDE_BEGIN_END(ctx)) {
  1095.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
  1096.       return;
  1097.    }
  1098.    if (count<0) {
  1099.       gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
  1100.       return;
  1101.    }
  1102.    switch (mode) {
  1103.       case GL_POINTS:
  1104.       case GL_LINES:
  1105.       case GL_LINE_STRIP:
  1106.       case GL_LINE_LOOP:
  1107.       case GL_TRIANGLES:
  1108.       case GL_TRIANGLE_STRIP:
  1109.       case GL_TRIANGLE_FAN:
  1110.       case GL_QUADS:
  1111.       case GL_QUAD_STRIP:
  1112.       case GL_POLYGON:
  1113.          /* OK */
  1114.          break;
  1115.       default:
  1116.          gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
  1117.          return;
  1118.    }
  1119.    switch (type) {
  1120.       case GL_UNSIGNED_BYTE:
  1121.          {
  1122.             GLubyte *ub_indices = (GLubyte *) indices;
  1123.             GLint i;
  1124.             gl_Begin( ctx, mode );
  1125.             for (i=0;i<count;i++) {
  1126.                gl_ArrayElement( ctx, (GLint) ub_indices[i] );
  1127.             }
  1128.             gl_End( ctx );
  1129.          }
  1130.          break;
  1131.       case GL_UNSIGNED_SHORT:
  1132.          {
  1133.             GLushort *us_indices = (GLushort *) indices;
  1134.             GLint i;
  1135.             gl_Begin( ctx, mode );
  1136.             for (i=0;i<count;i++) {
  1137.                gl_ArrayElement( ctx, (GLint) us_indices[i] );
  1138.             }
  1139.             gl_End( ctx );
  1140.          }
  1141.          break;
  1142.       case GL_UNSIGNED_INT:
  1143.          {
  1144.             GLuint *ui_indices = (GLuint *) indices;
  1145.             GLint i;
  1146.             gl_Begin( ctx, mode );
  1147.             for (i=0;i<count;i++) {
  1148.                gl_ArrayElement( ctx, (GLint) ui_indices[i] );
  1149.             }
  1150.             gl_End( ctx );
  1151.          }
  1152.          break;
  1153.       default:
  1154.          gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
  1155.          return;
  1156.    }
  1157. }
  1158.  
  1159.  
  1160.  
  1161.  
  1162. /*
  1163.  * Save (and perhaps execute)
  1164.  */
  1165. void gl_save_DrawElements( GLcontext *ctx,
  1166.                            GLenum mode, GLsizei count,
  1167.                            GLenum type, const GLvoid *indices )
  1168. {
  1169.    switch (type) {
  1170.       case GL_UNSIGNED_BYTE:
  1171.          {
  1172.             GLubyte *ub_indices = (GLubyte *) indices;
  1173.             GLint i;
  1174.             gl_save_Begin( ctx, mode );
  1175.             for (i=0;i<count;i++) {
  1176.                gl_save_ArrayElement( ctx, (GLint) ub_indices[i] );
  1177.             }
  1178.             gl_save_End( ctx );
  1179.          }
  1180.          break;
  1181.       case GL_UNSIGNED_SHORT:
  1182.          {
  1183.             GLushort *us_indices = (GLushort *) indices;
  1184.             GLint i;
  1185.             gl_save_Begin( ctx, mode );
  1186.             for (i=0;i<count;i++) {
  1187.                gl_save_ArrayElement( ctx, (GLint) us_indices[i] );
  1188.             }
  1189.             gl_save_End( ctx );
  1190.          }
  1191.          break;
  1192.       case GL_UNSIGNED_INT:
  1193.          {
  1194.             GLuint *ui_indices = (GLuint *) indices;
  1195.             GLint i;
  1196.             gl_save_Begin( ctx, mode );
  1197.             for (i=0;i<count;i++) {
  1198.                gl_save_ArrayElement( ctx, (GLint) ui_indices[i] );
  1199.             }
  1200.             gl_save_End( ctx );
  1201.          }
  1202.          break;
  1203.       default:
  1204.          gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
  1205.          return;
  1206.    }
  1207. }
  1208.  
  1209.  
  1210.  
  1211. void gl_InterleavedArrays( GLcontext *ctx,
  1212.                            GLenum format, GLsizei stride,
  1213.                            const GLvoid *pointer )
  1214. {
  1215.    GLboolean tflag, cflag, nflag;  /* enable/disable flags */
  1216.    GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
  1217.    GLenum ctype;                   /* color type */
  1218.    GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
  1219.    GLint defstride;                /* default stride */
  1220.    GLint c, f;
  1221.    GLint coordSetSave;
  1222.  
  1223.    f = sizeof(GLfloat);
  1224.    c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
  1225.  
  1226.    if (stride<0) {
  1227.       gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
  1228.       return;
  1229.    }
  1230.  
  1231.    switch (format) {
  1232.       case GL_V2F:
  1233.          tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1234.          tcomps = 0;  ccomps = 0;  vcomps = 2;
  1235.          voffset = 0;
  1236.          defstride = 2*f;
  1237.          break;
  1238.       case GL_V3F:
  1239.          tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1240.          tcomps = 0;  ccomps = 0;  vcomps = 3;
  1241.          voffset = 0;
  1242.          defstride = 3*f;
  1243.          break;
  1244.       case GL_C4UB_V2F:
  1245.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1246.          tcomps = 0;  ccomps = 4;  vcomps = 2;
  1247.          ctype = GL_UNSIGNED_BYTE;
  1248.          coffset = 0;
  1249.          voffset = c;
  1250.          defstride = c + 2*f;
  1251.          break;
  1252.       case GL_C4UB_V3F:
  1253.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1254.          tcomps = 0;  ccomps = 4;  vcomps = 3;
  1255.          ctype = GL_UNSIGNED_BYTE;
  1256.          coffset = 0;
  1257.          voffset = c;
  1258.          defstride = c + 3*f;
  1259.          break;
  1260.       case GL_C3F_V3F:
  1261.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1262.          tcomps = 0;  ccomps = 3;  vcomps = 3;
  1263.          ctype = GL_FLOAT;
  1264.          coffset = 0;
  1265.          voffset = 3*f;
  1266.          defstride = 6*f;
  1267.          break;
  1268.       case GL_N3F_V3F:
  1269.          tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
  1270.          tcomps = 0;  ccomps = 0;  vcomps = 3;
  1271.          noffset = 0;
  1272.          voffset = 3*f;
  1273.          defstride = 6*f;
  1274.          break;
  1275.       case GL_C4F_N3F_V3F:
  1276.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
  1277.          tcomps = 0;  ccomps = 4;  vcomps = 3;
  1278.          ctype = GL_FLOAT;
  1279.          coffset = 0;
  1280.          noffset = 4*f;
  1281.          voffset = 7*f;
  1282.          defstride = 10*f;
  1283.          break;
  1284.       case GL_T2F_V3F:
  1285.          tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1286.          tcomps = 2;  ccomps = 0;  vcomps = 3;
  1287.          voffset = 2*f;
  1288.          defstride = 5*f;
  1289.          break;
  1290.       case GL_T4F_V4F:
  1291.          tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1292.          tcomps = 4;  ccomps = 0;  vcomps = 4;
  1293.          voffset = 4*f;
  1294.          defstride = 8*f;
  1295.          break;
  1296.       case GL_T2F_C4UB_V3F:
  1297.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1298.          tcomps = 2;  ccomps = 4;  vcomps = 3;
  1299.          ctype = GL_UNSIGNED_BYTE;
  1300.          coffset = 2*f;
  1301.          voffset = c+2*f;
  1302.          defstride = c+5*f;
  1303.          break;
  1304.       case GL_T2F_C3F_V3F:
  1305.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1306.          tcomps = 2;  ccomps = 3;  vcomps = 3;
  1307.          ctype = GL_FLOAT;
  1308.          coffset = 2*f;
  1309.          voffset = 5*f;
  1310.          defstride = 8*f;
  1311.          break;
  1312.       case GL_T2F_N3F_V3F:
  1313.          tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
  1314.          tcomps = 2;  ccomps = 0;  vcomps = 3;
  1315.          noffset = 2*f;
  1316.          voffset = 5*f;
  1317.          defstride = 8*f;
  1318.          break;
  1319.       case GL_T2F_C4F_N3F_V3F:
  1320.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
  1321.          tcomps = 2;  ccomps = 4;  vcomps = 3;
  1322.          ctype = GL_FLOAT;
  1323.          coffset = 2*f;
  1324.          noffset = 6*f;
  1325.          voffset = 9*f;
  1326.          defstride = 12*f;
  1327.          break;
  1328.       case GL_T4F_C4F_N3F_V4F:
  1329.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
  1330.          tcomps = 4;  ccomps = 4;  vcomps = 4;
  1331.          ctype = GL_FLOAT;
  1332.          coffset = 4*f;
  1333.          noffset = 8*f;
  1334.          voffset = 11*f;
  1335.          defstride = 15*f;
  1336.          break;
  1337.       default:
  1338.          gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
  1339.          return;
  1340.    }
  1341.  
  1342.    if (stride==0) {
  1343.       stride = defstride;
  1344.    }
  1345.  
  1346.    gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY );
  1347.    gl_DisableClientState( ctx, GL_INDEX_ARRAY );
  1348.  
  1349.    coordSetSave = ctx->TexCoordSet;
  1350.    if (tflag) {
  1351.       GLint i;
  1352.       for (i = 0; i < ctx->Array.TexCoordInterleaveFactor; i++) {
  1353.          gl_SelectTextureCoordSet( ctx, GL_TEXTURE0_EXT + i );
  1354.          gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
  1355.          gl_TexCoordPointer( ctx, tcomps, GL_FLOAT, stride,
  1356.                              (GLubyte *) pointer + i * coffset );
  1357.       }
  1358.       for (i = 0; i < MAX_TEX_COORD_SETS; i++) {
  1359.          gl_SelectTextureCoordSet( ctx, GL_TEXTURE0_EXT + i );
  1360.          gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
  1361.       }
  1362.    }
  1363.    else {
  1364.       GLint i;
  1365.       for (i = 0; i < MAX_TEX_COORD_SETS; i++) {
  1366.          gl_SelectTextureCoordSet( ctx, GL_TEXTURE0_EXT + i );
  1367.          gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
  1368.       }
  1369.    }
  1370.    /* Restore texture coordinate set index */
  1371.    gl_SelectTextureCoordSet( ctx, coordSetSave );
  1372.  
  1373.    if (cflag) {
  1374.       gl_EnableClientState( ctx, GL_COLOR_ARRAY );
  1375.       gl_ColorPointer( ctx, ccomps, ctype, stride,
  1376.                        (GLubyte*) pointer + coffset );
  1377.    }
  1378.    else {
  1379.       gl_DisableClientState( ctx, GL_COLOR_ARRAY );
  1380.    }
  1381.  
  1382.    if (nflag) {
  1383.       gl_EnableClientState( ctx, GL_NORMAL_ARRAY );
  1384.       gl_NormalPointer( ctx, GL_FLOAT, stride,
  1385.                         (GLubyte*) pointer + noffset );
  1386.    }
  1387.    else {
  1388.       gl_DisableClientState( ctx, GL_NORMAL_ARRAY );
  1389.    }
  1390.  
  1391.    gl_EnableClientState( ctx, GL_VERTEX_ARRAY );
  1392.    gl_VertexPointer( ctx, vcomps, GL_FLOAT, stride,
  1393.                      (GLubyte *) pointer + voffset );
  1394. }
  1395.  
  1396.  
  1397.  
  1398. void gl_save_InterleavedArrays( GLcontext *ctx,
  1399.                                 GLenum format, GLsizei stride,
  1400.                                 const GLvoid *pointer )
  1401. {
  1402.    /* Just execute since client-side state changes aren't put in
  1403.     * display lists.
  1404.     */
  1405.    gl_InterleavedArrays( ctx, format, stride, pointer );
  1406. }
  1407.  
  1408.  
  1409.  
  1410. void gl_DrawRangeElements( GLcontext *ctx, GLenum mode, GLuint start,
  1411.                            GLuint end, GLsizei count, GLenum type,
  1412.                            const GLvoid *indices )
  1413. {
  1414.    /* XXX TODO optimize this function someday- it would be worthwhile */
  1415.    if (end < start) {
  1416.       gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
  1417.       return;
  1418.    }
  1419.    (void) start;
  1420.    (void) end;
  1421.    gl_DrawElements( ctx, mode, count, type, indices );
  1422. }
  1423.  
  1424.  
  1425. void gl_save_DrawRangeElements( GLcontext *ctx, GLenum mode,
  1426.                                 GLuint start, GLuint end, GLsizei count,
  1427.                                 GLenum type, const GLvoid *indices )
  1428. {
  1429.    /* XXX TODO optimize this function someday- it would be worthwhile */
  1430.    (void) start;
  1431.    (void) end;
  1432.    gl_save_DrawElements( ctx, mode, count, type, indices );
  1433. }
  1434.